home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-12 | 5.7 KB | 183 lines | [TEXT/KAHL] |
- /*-------------------------------------------------
- Steve Israelson
- Motion Works Corp.
- -------------------------------------------------*/
- void RotateBitMapClockwise(BitMap *, BitMap *);
- void rotateBlock(unsigned long *,unsigned char *,
- long,unsigned char *,long);
- void rotateLimitedBlock(unsigned long *,
- unsigned char *, long,unsigned char *,long,
- short);
-
-
- /*-------------------------------------------------
- Rotate the bitmap from src to dst by +90 degrees.
- Make a table for use in the rotate block routine.
- Step through the src in 8x8 blocks, starting from
- the bottom left. Step through dst in 8x8 blocks,
- starting from the top left. Handle the right edge
- of the bitmap specially to prevent bits from being
- rotated into memory outside of the destination.
- -------------------------------------------------*/
- void RotateBitMapClockwise(BitMap *src, BitMap *dst)
- {
- unsigned long table[16] =
- {0x00000000, 0x00000001, 0x00000100, 0x00000101,
- 0x00010000, 0x00010001, 0x00010100, 0x00010101,
- 0x01000000, 0x01000001, 0x01000100, 0x01000101,
- 0x01010000, 0x01010001, 0x01010100, 0x01010101};
- /* x,y co-ord of source block */
- register short srcX, srcY;
- /* row bytes, dereferenced for speed */
- short srcRowBytes, dstRowBytes;
- /* src rowbytes * 8, for speed */
- short srcRowX8;
- /* width and height of src */
- short srcWidth, srcHeight;
- /* pointer to src and dst 8x8 blocks */
- char *srcData, *dstData;
- /* pointer to bitmaps de-referenced for speed */
- char *srcAddr, *dstAddr;
- /* last few pixels to do specially */
- short remainder;
- /* a constant, pre-calculated for speed */
- char *const1;
-
- /* de-reference some constants */
- srcRowBytes = src->rowBytes;
- dstRowBytes = dst->rowBytes;
- srcAddr = src->baseAddr;
- dstAddr = dst->baseAddr;
-
- /* calculate some values */
- srcWidth = src->bounds.right - src->bounds.left;
- srcHeight = src->bounds.bottom - src->bounds.top;
-
- srcRowX8 = srcRowBytes * 8;
- const1 = srcAddr + (srcHeight - 8) * srcRowBytes;
-
- /* loop through the source doing vertical
- * slices starting at the left */
- for (srcX = 0; srcX < srcWidth - 7; srcX += 8) {
- /* bottom edge */
- srcData = const1 + srcX / 8;
- /* left edge */
- dstData = dstAddr + srcX * dstRowBytes;
- for (srcY = srcHeight - 1; srcY >= 0;
- srcY -= 8 ) {
- rotateBlock(table, (unsigned char *)srcData,
- srcRowBytes, (unsigned char *)dstData,
- dstRowBytes);
- srcData -= srcRowX8; /* next vert block */
- ++dstData; /* next horiz block */
- }
- }
-
- /* handle the last partial row by calling
- * rotateLimitedBlock() */
- if (remainder = (srcWidth % 8)) {
- /* bottom edge */
- srcData = const1 + srcX / 8;
- /* left edge */
- dstData = dstAddr + srcX * dstRowBytes;
- for (srcY = srcHeight - 1; srcY >= 0;
- srcY -= 8 ) {
- rotateLimitedBlock(table,
- (unsigned char *)srcData, srcRowBytes,
- (unsigned char *)dstData, dstRowBytes,
- remainder);
- srcData -= srcRowX8;
- ++dstData;
- }
- }
- }
-
- /*-------------------------------------------------
- Rotate an 8x8 block of pixels by treating the
- destination block as 2 unsigned longs (64 bits!)
- and using a lookup table to get a mask for the
- value of each row in the src block. The table
- essentially stretches out the source byte to 8
- times its size and then ORs it into the
- destination 64bits. Since the bits are in the
- low bit of each byte, the destination has to be
- shifted one position to the left before each OR
- operation. The offset values are the difference
- in bytes between each row of pixels, equivalent
- to rowBytes. If we had a 64bit data type, this
- would be easier.
- -------------------------------------------------*/
- void rotateBlock(unsigned long *table,
- unsigned char *src, long srcOffset,
- unsigned char *dst, long dstOffset)
- {
- register unsigned long resultLO, resultHi;
- short x;
-
- resultLO = resultHi = 0;
- src += srcOffset * 7;
- /* compute the rotated result */
- for (x = 0; x < 8; ++x) {
- resultLO = resultLO << 1;
- resultHi = resultHi << 1;
- resultLO |= table[(*src) >> 4];
- resultHi |= table[(*src) & 0x0F];
- src -= srcOffset;
- }
-
- /* store the rotated result */
- *dst = (resultLO & 0xFF000000) >> 24;
- dst += dstOffset;
- *dst = (resultLO & 0x00FF0000) >> 16;
- dst += dstOffset;
- *dst = (resultLO & 0x0000FF00) >> 8;
- dst += dstOffset;
- *dst = resultLO & 0x000000FF;
- dst += dstOffset;
- *dst = (resultHi & 0xFF000000) >> 24;
- dst += dstOffset;
- *dst = (resultHi & 0x00FF0000) >> 16;
- dst += dstOffset;
- *dst = (resultHi & 0x0000FF00) >> 8;
- dst += dstOffset;
- *dst = resultHi & 0x000000FF;
- }
-
- /*-------------------------------------------------
- Same as other rotateBlock, except will do a
- partial block. Useful to prevent the overwriting
- of memory outside the bitmap!
- -------------------------------------------------*/
- void rotateLimitedBlock(unsigned long *table,
- unsigned char *src, long srcOffset,
- unsigned char *dst, long dstOffset, short lines)
- {
- register unsigned long resultLO, resultHi;
- short x;
-
- resultLO = resultHi = 0;
- src += srcOffset * 7;
- for (x = 0; x < 8; ++x) {
- resultLO = resultLO << 1;
- resultHi = resultHi << 1;
- resultLO |= table[(*src) >> 4];
- resultHi |= table[(*src) & 0x0F];
- src -= srcOffset;
- }
- *dst = (resultLO & 0xFF000000) >> 24;
- dst += dstOffset; if (lines == 1) return;
- *dst = (resultLO & 0x00FF0000) >> 16;
- dst += dstOffset; if (lines == 2) return;
- *dst = (resultLO & 0x0000FF00) >> 8;
- dst += dstOffset; if (lines == 3) return;
- *dst = resultLO & 0x000000FF;
- dst += dstOffset; if (lines == 4) return;
- *dst = (resultHi & 0xFF000000) >> 24;
- dst += dstOffset; if (lines == 5) return;
- *dst = (resultHi & 0x00FF0000) >> 16;
- dst += dstOffset; if (lines == 6) return;
- *dst = (resultHi & 0x0000FF00) >> 8;
- dst += dstOffset; if (lines == 7) return;
- *dst = resultHi & 0x000000FF;
- }
-